package bma.common.langutil.jmshell.command;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;

import bma.common.langutil.core.ValueUtil;
import bma.common.langutil.jmshell.Session;
import bma.common.langutil.jmshell.cmdopt.CommandOptionParser;

public class CfgCommand extends AbstractSimpleCommandProcessor {

	public static final String DATA_KEY = "@cfg_data";

	public CfgCommand() {
		super("cfg");
		setArgsTips("[commandName] [\"@config\"] ...");
	}

	@Override
	public CommandOptionParser createCommandOption(Session session) {
		CommandOptionParser r = new CommandOptionParser();
		r.addBooleanOption('a', "all", "show all command config");
		r.addBooleanOption((char) 0, "clear", "reset all command config");

		r.addBooleanOption('r', "reset", "reset command config");
		r.addBooleanOption('e', "edit",
				"replace command config, default append config");
		r.addBooleanOption('l', "list", "show command config");
		return r;
	}

	@Override
	public boolean processCommand(Session session, String cmd,
			CommandOptionParser options) {
		if (options.getOptionValue("all", Boolean.FALSE)) {
			showAll(session);
			return true;
		}
		if (options.getOptionValue("clear", Boolean.FALSE)) {
			clear(session);
			return true;
		}
		String[] args = options.getRemainingArgs();
		if (options.getOptionValue("reset", Boolean.FALSE)) {
			reset(session, args);
			return true;
		}
		if (options.getOptionValue("edit", Boolean.FALSE)) {
			edit(session, args);
			return true;
		}
		if (options.getOptionValue("list", Boolean.FALSE)) {
			show(session, args);
			return true;
		}
		if (args == null || args.length == 0) {
			showAll(session);
			return true;
		}
		append(session, args);
		return true;
	}

	protected static Map<String, String> getData(Session s, boolean sure) {
		@SuppressWarnings("unchecked")
		Map<String, String> data = (Map<String, String>) s
				.getAttribute(DATA_KEY);
		if (data == null && sure) {
			data = Collections.synchronizedMap(new HashMap<String, String>());
			s.setAttribute(DATA_KEY, data);
		}
		return data;
	}

	public void showAll(Session s) {
		Map<String, String> data = getData(s, false);
		s.writeln("[config]");
		if (data != null) {
			TreeMap<String, String> tmp = new TreeMap<String, String>(data);
			for (Map.Entry<String, String> e : tmp.entrySet()) {
				StringBuilder sb = new StringBuilder();
				sb.append(e.getKey()).append(": ").append(e.getValue());
				s.writeln(sb.toString());
			}
		}
		s.writeln("[config end]");
	}

	public void clear(Session s) {
		Map<String, String> data = getData(s, false);
		if (data != null) {
			data.clear();
		}
		s.writeln("config clear done");
	}

	public void show(Session s, String[] remains) {
		if (remains == null || remains.length == 0) {
			s.writeln("ERROR: input config name");
			return;
		}
		String name = remains[0];
		Map<String, String> data = getData(s, false);
		s.writeln("[config]");
		if (data != null) {
			String cfg = data.get(name);
			StringBuilder sb = new StringBuilder();
			sb.append(name).append(": ").append(cfg == null ? "" : cfg);
			s.writeln(sb.toString());
		}
		s.writeln("[config end]");
	}

	public void reset(Session s, String[] remains) {
		if (remains == null || remains.length == 0) {
			s.writeln("ERROR: input config name");
			return;
		}
		String name = remains[0];
		Map<String, String> data = getData(s, false);
		if (data != null) {
			data.remove(name);
		}
		s.writeln("config '" + name + "' reset done");
	}

	public void edit(Session s, String[] remains) {
		if (remains == null || remains.length == 0) {
			s.writeln("ERROR: input config name");
			return;
		}
		String name = remains[0];
		if (remains.length < 2) {
			s.writeln("ERROR: input config value");
		}
		String cfg = remains[1];
		if (cfg.startsWith("@")) {
			cfg = cfg.substring(1);
		}
		Map<String, String> data = getData(s, true);
		data.put(name, cfg);
		s.writeln("config '" + name + "' edit done => " + cfg);
	}

	public void append(Session s, String[] remains) {
		if (remains == null || remains.length == 0) {
			s.writeln("ERROR: input config name");
			return;
		}
		String name = remains[0];
		if (remains.length < 2) {
			s.writeln("ERROR: input config value");
		}
		Map<String, String> data = getData(s, true);
		StringBuilder sb = new StringBuilder();
		if (data.containsKey(name)) {
			sb.append(data.get(name));
		}
		for (int i = 1; i < remains.length; i++) {
			String cfg = remains[i];
			if (cfg.startsWith("@")) {
				cfg = cfg.substring(1);
			}
			sb.append(" ");
			sb.append(cfg);
		}
		data.put(name, sb.toString());
		s.writeln("config '" + name + "' append done => " + sb.toString());
	}

	public static String makeCommand(Session session, String command) {
		if (command == null)
			return null;
		Map<String, String> data = getData(session, false);
		if (data != null && !data.isEmpty()) {
			String[] cmds = command.split(" ", 2);
			String cmd = cmds[0].trim();
			String cfg = data.get(cmd);
			if (ValueUtil.notEmpty(cfg)) {
				command += " " + cfg;
				session.writeln(">> " + command);
			}
		}
		return command;
	}
}